;****************************************************************************************************
; klib_syscall_entry.asm
;
; contains the x64 syscall entry point code
;
; Author: Aidan Goddard 18/8/13
;
;****************************************************************************************************

global __KLIB__SyscallEntry
extern __KLIB__function_group_array

section .text

align 16

; should be called with:
; rax = function group number
; rbx = sub-function number

; rdi = 1st argument
; rsi = 2nd argument
; rdx = 3rd argument
; r10 = 4th argument
; r8 = 5th argument
; r9 = 6th argument

__KLIB__SyscallEntry:
	; rcx and r11 contain the return RIP and RFLAGS, save them on the stack
	push 	r11
	push 	rcx

	; need to save GP registers that are trashed by the System V C calling convention + rbx
	push 	rbx
	push 	rdx
	push 	rsi
	push 	rdi
	push 	r8
	push 	r9
	push 	r10

	; check for 0 values in rax and rbx (invalid values)
	or 		rax, rax
	jz		.finish
	or 		rbx, rbx
	jz 		.finish

	; check rax for > 64
	cmp 	rax, 64
	jge		.finish

	; fix the 4th argument
	mov 	rcx, r10

	; rax = function group
	; rbx = sub-function number
	; __KLIB__FunctionGroupArray is the base address of the function group call address array.
	; calculate address of the correct function group to call
	mov 	r10, __KLIB__function_group_array		; get base address of group array
	mov 	r10, [r10 + (rax * 8)]					; get address of selected group's array
	mov		r10, [r10 + (rbx * 8)]					; get address of function to call

	; call the function
	call 	r10

.finish:
	; restore System V trashed registers
	pop 	r10
	pop 	r9
	pop 	r8
	pop 	rdi
	pop 	rsi
	pop 	rdx
	pop 	rbx

	; finished, fetch RIP and RFLAGS and perform x64 sysret
	pop 	rcx
	pop 	r11
	o64 sysret		; force REX prefix with 'o64' otherwise the CPU will return in compatability mode
